<template>
  <div class="base-input" :class="wrapperClasses">
    <label v-if="label" class="input-label" :for="inputId">
      {{ label }}
      <span v-if="required" class="required-mark">*</span>
    </label>
    
    <div class="input-wrapper">
      <div v-if="$slots.prepend || prependIcon" class="input-prepend">
        <slot name="prepend">
          <div v-if="prependIcon" class="input-icon" v-html="prependIcon" />
        </slot>
      </div>
      
      <input
        :id="inputId"
        v-bind="$attrs"
        :type="type"
        :value="modelValue"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :required="required"
        class="input-element"
        @input="handleInput"
        @change="handleChange"
        @blur="handleBlur"
        @focus="handleFocus"
      />
      
      <div v-if="$slots.append || appendIcon || clearable" class="input-append">
        <button
          v-if="clearable && modelValue"
          type="button"
          class="input-clear"
          @click="handleClear"
        >
          <svg class="input-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
        <slot name="append">
          <div v-if="appendIcon" class="input-icon" v-html="appendIcon" />
        </slot>
      </div>
    </div>
    
    <div v-if="hint || error" class="input-message">
      <span v-if="error" class="error-text">{{ error }}</span>
      <span v-else-if="hint" class="hint-text">{{ hint }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import type { Component } from 'vue'

interface Props {
  modelValue: string | number
  type?: string
  label?: string
  placeholder?: string
  hint?: string
  error?: string
  disabled?: boolean
  readonly?: boolean
  required?: boolean
  clearable?: boolean
  prependIcon?: Component | string
  appendIcon?: Component | string
  size?: 'sm' | 'md' | 'lg'
}

interface Emits {
  (e: 'update:modelValue', value: string): void
  (e: 'change', value: string): void
  (e: 'blur', event: FocusEvent): void
  (e: 'focus', event: FocusEvent): void
  (e: 'clear'): void
}

const props = withDefaults(defineProps<Props>(), {
  type: 'text',
  size: 'md'
})

const emit = defineEmits<Emits>()

const inputId = computed(() => `input-${Math.random().toString(36).substr(2, 9)}`)

const wrapperClasses = computed(() => [
  'base-input-wrapper',
  `input-${props.size}`,
  {
    'input-disabled': props.disabled,
    'input-error': props.error,
    'input-has-prepend': props.prependIcon,
    'input-has-append': props.appendIcon || props.clearable
  }
])

const handleInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  emit('update:modelValue', target.value)
}

const handleChange = (event: Event) => {
  const target = event.target as HTMLInputElement
  emit('change', target.value)
}

const handleBlur = (event: FocusEvent) => {
  emit('blur', event)
}

const handleFocus = (event: FocusEvent) => {
  emit('focus', event)
}

const handleClear = () => {
  emit('update:modelValue', '')
  emit('clear')
}
</script>

<style scoped>
.base-input {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.input-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 4px;
}

.required-mark {
  color: var(--danger);
  font-weight: 600;
}

.input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card-bg);
  transition: all 0.2s ease;
}

.input-wrapper:hover {
  border-color: var(--border-dark);
}

.input-wrapper:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

.input-element {
  flex: 1;
  width: 100%;
  border: none;
  outline: none;
  background: transparent;
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
}

.input-element::placeholder {
  color: var(--text-light);
}

.input-element:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.input-prepend,
.input-append {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  flex-shrink: 0;
}

.input-prepend {
  padding-left: 12px;
}

.input-append {
  padding-right: 12px;
}

.input-has-prepend .input-element {
  padding-left: 8px;
}

.input-has-append .input-element {
  padding-right: 8px;
}

.input-sm .input-element {
  height: 32px;
  font-size: 13px;
}

.input-md .input-element {
  height: 40px;
  font-size: 14px;
}

.input-lg .input-element {
  height: 48px;
  font-size: 16px;
}

.input-sm .input-prepend {
  padding-left: 8px;
}

.input-sm .input-append {
  padding-right: 8px;
}

.input-lg .input-prepend {
  padding-left: 16px;
}

.input-lg .input-append {
  padding-right: 16px;
}

.input-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.input-clear {
  background: none;
  border: none;
  padding: 4px;
  margin: -4px;
  cursor: pointer;
  color: var(--text-muted);
  border-radius: 4px;
  transition: all 0.2s ease;
}

.input-clear:hover {
  color: var(--text-secondary);
  background: var(--bg-secondary);
}

.input-message {
  font-size: 12px;
  line-height: 1.4;
  min-height: 16px;
}

.hint-text {
  color: var(--text-muted);
}

.error-text {
  color: var(--danger);
  font-weight: 500;
}

.input-error .input-wrapper {
  border-color: var(--danger);
}

.input-error .input-wrapper:focus-within {
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);
}

@media (max-width: 768px) {
  .input-md .input-element {
    height: 44px;
    font-size: 16px;
  }
  
  .input-lg .input-element {
    height: 52px;
    font-size: 18px;
  }
}
</style>